let select_click = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
/**
 * 名称：模型高亮
 * 作用：点击模型进行高亮
 * 状态：已完成
 * 参数：
 * @param
 *  负责人：杨世林
 */
const select = () => {
  // 高亮元素
  const hightLighted = {
    feautre: undefined,
    originalColor: new Cesium.Color(),
  }

  select_click.setInputAction(function onLeftClick(event) {
    // 清除之前的高亮元素
    if (Cesium.defined(hightLighted.feature)) {
      hightLighted.feature.color = hightLighted.originalColor;
      hightLighted.feature = undefined;
    }

    // 选择新要素
    const pickedFeature = viewer.scene.pick(event.position);
    if (!Cesium.defined(pickedFeature)) {
      return;
    }
    // 存储选中要素的信息
    hightLighted.feature = pickedFeature;
    Cesium.Color.clone(
        pickedFeature.color,
        hightLighted.originalColor
    );
    // 高亮选中元素
    pickedFeature.color = Cesium.Color.RED.withAlpha(0.5);
  }, Cesium.ScreenSpaceEventType.LEFT_DOWN)
}

/**
 * 禁用选中构件
 */
const disableSelected = () => {
  tileset.style = new Cesium.Cesium3DTileStyle({
    color: `color('rgba(255,255,255,1)')`
  })
  select_click.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN)
}

/**
 * 名称：模型通过高度进行剖切
 * 作用：传入指定的高度进行剖切
 * 参数：剖切的高度
 * @param height  剖切的高度
 * @returns {Promise<unknown>}
 */
const horizontalCutting = (height) => {
  // 定义一个ClippingPlaneCollection类，用来存储裁剪面
  clippingPlanes = new Cesium.ClippingPlaneCollection({
    planes : [
      // ClippingPlane对象数组集合
      new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 0.0, -1.0), // 法线方向
          0.0  // 原点到平面的最短距离，设置0就好
      ),
    ],
    // edgeColor: Cesium.Color.RED,
    edgeWidth: 1.0, // 模型被裁切部分的截面线宽
    unionClippingRegions: true, //true 才能多个切割
  });

  for (let globalTilesetArrKey of globalTilesetArr) {
    globalTilesetArrKey.clippingPlanes = clippingPlanes;
  }
  for (let i = 0; i < clippingPlanes.length; ++i) {
    let plane = clippingPlanes.get(i);
    plane.distance = height
  }
}

/**
 * 名称：退出剖切操作
 * 作用：还原被剖切的模型
 */
const exitCutting = () => {
  for (let vsTilesetKey of globalTilesetArr) {
    vsTilesetKey.clippingPlanes = new Cesium.ClippingPlaneCollection()
  }
}

/**
 * 距离量算，计算两点的距离
 * @param firstPoint 第一个点
 * @param secondPoint 第二个点
 * @returns 两点的距离
 */
const distanceMeasurement = (firstPoint,secondPoint) => {
  return Cesium.Cartesian3.distance(firstPoint,secondPoint).toFixed(2)
}

/**
 * 角度量算
 * @param firstPoint 第一个点 （中点）
 * @param secondPoint 第二个点
 * @param thirdPoint  第三个点
 * @returns 返回角度
 */
const angularMeasurement = (firstPoint,secondPoint,thirdPoint) => {
  // 得到 p1p2 的方向向量
  let c1 = Cesium.Cartesian3.subtract(secondPoint, firstPoint, new Cesium.Cartesian3());
  let c2 = Cesium.Cartesian3.subtract(thirdPoint, firstPoint, new Cesium.Cartesian3());
  // 计算两向量的夹角
  let angle = Cesium.Cartesian3.angleBetween(c1, c2);
  return ((angle * 180) / Math.PI).toFixed(2);
}

/**
 * 距离量算，计算两点的水平距离
 * @param firstPoint 第一个点
 * @param secondPoint 第二个点
 * @returns 两点的水平距离
 */
const horizontalDistanceMeasurement = (firstPoint,secondPoint) => {
  // 计算第三点
  function returnHeightPosition(positionsone, positionstwo){
    let point1cartographic = Cesium.Cartographic.fromCartesian(positionsone);
    let point2cartographic = Cesium.Cartographic.fromCartesian(positionstwo);
    return Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees(point1cartographic.longitude), Cesium.Math.toDegrees(point1cartographic.latitude), point2cartographic.height)
  }
  let thirdPoint = returnHeightPosition(firstPoint,secondPoint)
  return Cesium.Cartesian3.distance(thirdPoint,secondPoint).toFixed(2)
}
/**
 * 距离量算，计算两点的垂直距离
 * @param firstPoint 第一个点
 * @param secondPoint 第二个点
 * @returns 两点的垂直距离
 */
const verticalDistanceMeasurement = (firstPoint,secondPoint) => {
  let point1cartographic = Cesium.Cartographic.fromCartesian(firstPoint);
  let point2cartographic = Cesium.Cartographic.fromCartesian(secondPoint);
  return Math.abs(point1cartographic.height - point2cartographic.height).toFixed(2)
}


/**
 * 名称：坐标拾取
 * 说明：拾取位置点，能够根据鼠标位置判断出是画在3dtils上，还是画在地球上，还是画在地形上
 * 参数： position： 屏幕坐标
 * 返回值：Cartesian3 三维坐标
 * 负责人：/
 * 网址：http://www.5imoban.net/jiaocheng/mapgis/202106224870.html
 */
const positionPicking = (position) => {
  if(viewer && position) {
    var picks = viewer.scene.drillPick(position)
    var cartesian = null
    var isOn3dtiles = false, isOnTerrain = false
    // drillPick
    for(let i in picks) {
      let pick = picks[i]
      if(
          (pick && pick.primitive instanceof Cesium.Cesium3DTileFeature) ||
          (pick && pick.primitive instanceof Cesium.Cesium3DTileset) ||
          (pick && pick.primitive instanceof Cesium.Model)
      ) {
        //模型上拾取
        isOn3dtiles = true
      }
      // 3dtilset
      if(isOn3dtiles) {
        console.error('选中的是3dtilset')
        viewer.scene.pick(position) // pick
        cartesian = viewer.scene.pickPosition(position)
        if(cartesian) {
          let cartographic = Cesium.Cartographic.fromCartesian(cartesian)
          if(cartographic.height < 0) cartographic.height = 0
          let lon = Cesium.Math.toDegrees(cartographic.longitude),
              lat = Cesium.Math.toDegrees(cartographic.latitude),
              height = cartographic.height
          cartesian = this.transformWGS84ToCartesian({
            lng: lon,
            lat: lat,
            alt: height
          })
        }
      }
    }
    // 地形
    let boolTerrain =
        viewer.terrainProvider instanceof
        Cesium.EllipsoidTerrainProvider
    // Terrain
    if(!isOn3dtiles && !boolTerrain) {
      console.error('选中的是地形')
      var ray = viewer.scene.camera.getPickRay(position)
      if(!ray) return null
      cartesian = viewer.scene.globe.pick(ray, viewer.scene)
      isOnTerrain = true
    }
    // 地球
    if(!isOn3dtiles && !isOnTerrain && boolTerrain) {
      console.error('选中的是地球')
      cartesian = viewer.scene.camera.pickEllipsoid(
          position,
          viewer.scene.globe.ellipsoid
      )
    }
    if(cartesian) {
      let position = this.transformCartesianToWGS84(cartesian)
      if(position.alt < 0) {
        cartesian = this.transformWGS84ToCartesian(position, 0.1)
      }
      return cartesian
    }
    return false
  }
}

/**
 * 名称：坐标转换 笛卡尔转84
 * 说明：坐标转换 笛卡尔转84
 * 参数： cartesian： 三维位置坐标
 * 返回值：{lng,lat,alt} 地理坐标
 * 负责人：/
 * 网址：http://www.5imoban.net/jiaocheng/mapgis/202106224870.html
 */
function transformCartesianToWGS84(cartesian) {
  if(viewer && cartesian) {
    var ellipsoid = Cesium.Ellipsoid.WGS84
    var cartographic = ellipsoid.cartesianToCartographic(cartesian)
    return {
      lng: Cesium.Math.toDegrees(cartographic.longitude),
      lat: Cesium.Math.toDegrees(cartographic.latitude),
      alt: cartographic.height
    }
  }
}

/**
 * 名称：坐标转换 笛卡尔转84
 * 说明：坐标转换 笛卡尔转84
 * 参数： position： 三维位置坐标
 * 返回值：Cartesian3 三维位置坐标
 * 负责人：/
 * 网址：http://www.5imoban.net/jiaocheng/mapgis/202106224870.html
 */
function transformWGS84ToCartesian(position, alt) {
  if(viewer) {
    return position ?
        Cesium.Cartesian3.fromDegrees(
            position.lng || position.lon,
            position.lat,
            position.alt = alt || position.alt,
            Cesium.Ellipsoid.WGS84
        ) :
        Cesium.Cartesian3.ZERO
  }
}


/**
 * 绘制点
 * @param id 点的id
 * @param name 点的名称
 * @param position 点的坐标
 * @param color 点的颜色
 * @param outlineColor 点的轮廓颜色
 * @returns {*}
 */
const drawPoint = (id,name,position,color = Cesium.Color.WHEAT,outlineColor = Cesium.Color.WHEAT) => {
  return viewer.entities.add({
    id: id,
    name: name,
    position: position,
    point: {
      color: color,
      outlineColor: outlineColor,
      pixelSize: 5,
      outlineWidth: 3,
      disableDepthTestDistance: Number.POSITIVE_INFINITY
    }
  })
}

/**
 * 绘制直线
 * @param type 直线的类型  1 虚线  2 直线 3 箭头线
 * @param id 直线的id
 * @param name 直线的名称
 * @param positions 直线的坐标数组
 * @param color 指定用于绘制折线的材料。
 * @param outlineColor 指定折线低于地形时用于绘制折线的颜色。
 * @returns {*}
 */
const drawLine = (type,id,name,positions,color = Cesium.Color.YELLOW,outlineColor = Cesium.Color.WHEAT) => {
  if(type === 1){
    return viewer.entities.add({
      id: id,
      name: name,
      polyline: {
        positions: positions,
        width: 3,
        material: new Cesium.PolylineDashMaterialProperty({
          color: color,
          dashLength: 20 //短划线长度
        }),
        depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
          // eslint-disable-next-line new-cap
          color: outlineColor
        })
      }
    })
  }else if(type === 2){
    return viewer.entities.add({
      id: id,
      name: name,
      polyline: {
        positions: positions,
        width: 2,
        material: new Cesium.PolylineGlowMaterialProperty({
          color: color
        }),
        depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
          color: outlineColor
        }),
        // clampToGround: true // 贴地
        zIndex: 1
      }
    })
  }else if(type === 3){
    return viewer.entities.add({
      id: id,
      name: name,
      polyline: {
        positions: positions,
        width: 2,
        material: new Cesium.PolylineArrowMaterialProperty ({
          color: color
        }),
        depthFailMaterial: new Cesium.PolylineArrowMaterialProperty ({
          color: outlineColor
        }),
        // clampToGround: true // 贴地
        zIndex: 1
      }
    })
  }
}


/**
 * 设置构件颜色及透明度
 * @param id 构件id
 * @param option 配置项
 */
const setObjectsColor = (id, option) => {
  option = {
    alpha: 1,
    color: Cesium.Color.WHITE,
    ...option
  }
  // 赋予颜色
  all3dTilesObjArr[id] && (all3dTilesObjArr[id].color = option.color.withAlpha(option.alpha))
}

/**
 * 重置某个构件的颜色
 * @param id 构建的id
 */
const restoreObjectsColor = (id) => {
  all3dTilesObjArr[id].color = new Cesium.Color(255, 255, 255).withAlpha(1)
}

/**
 * @description 设置整个模型颜色透明度
 * @param option 配置项
 */
const setModelColor = (option) => {
  option = {
    color: [255, 255, 255],
    alpha: 1,
    ...option
  }
  // 透明整体建筑
  tileset.style = new Cesium.Cesium3DTileStyle({
    color: `color('rgba(${option.color[0]},${option.color[1]},${option.color[2]},${option.alpha})')`
  })
}

/**
 * @description 重置整个模型的颜色
 */
const restoreModelColor = () => {
  tileset.style = new Cesium.Cesium3DTileStyle({
    color: `color('rgba(255,255,255,1)')`
  })
}

/**
 * @description 根据传进来的keyName和valName，查找所有模糊匹配该字段的3dTiles数据
 * @param keyName 键名
 * @param valName 键值
 * @param num 查询数量
 */
function searchComponentAll(keyName, valName, num = 20) {
  let arr = []
  let count = num //计数
  all3dTilesArr && all3dTilesArr.map((item) => {
    if(count < 1) {
      return arr
    }
    if(item[keyName] && item[keyName].toString().includes(valName)) {
      arr.push({
        id: item.id,
        [keyName]: item[keyName]
      })
      count--
    }
  })
  return arr
}

// const testt = () => {
//   let dataArr = []
//   let line_click = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
//   line_click.setInputAction((movement)=>{
//     let point_star = positionPicking(movement.position)
//     dataArr.push(point_star)
//     let data = drawPoint(dataArr.length,'1',point_star)
//     console.log(data,point_star)
//     if(dataArr.length > 1){
//       let a = distanceMeasurement(dataArr[0],dataArr[1])
//       let b = horizontalDistanceMeasurement(dataArr[0],dataArr[1])
//       let c = verticalDistanceMeasurement(dataArr[0],dataArr[1])
//       let s=drawLine(3,'line','2',dataArr)
//       console.log(s)
//       line_click.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
//     }
//   },Cesium.ScreenSpaceEventType.LEFT_CLICK)
// }

/**
 * 名称：获取鼠标当前的位置
 * 作用：获取鼠标当前的坐标
 * 参数：Position  屏幕二位坐标 Cartesian2
 * @return 返回笛卡尔坐标  Cartesian3 如果选中的是点 线等返回false
 */
const getLocation = (Position) => {
  // 获取模型的坐标
  let pick = viewer.scene.pickPosition(Position)
  let pickModel = viewer.scene.pick(Position)
  if (pickModel && pick && !pickModel.id) {
    let height = Cesium.Cartographic.fromCartesian(pick).height;
    let lat = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(pick).latitude);
    let lng = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(pick).longitude);
    let cartesian = Cesium.Cartesian3.fromDegrees(lng, lat, height);
    console.log(1)
    return cartesian
  } else {
    // 如果是选中的点 线 标签等 返回false
    if(pickModel && pickModel.id){
      return false
    }
    // 获取椭圆或地图的坐标
    let cartesian = viewer.camera.pickEllipsoid(Position,viewer.scene.globe.ellipsoid)
    if(cartesian){
      console.log(2)
      return cartesian
    }else{
      // 获取地形坐标
      let ray1 = viewer.camera.getPickRay(Position)
      let cartesian = viewer.scene.globe.pick(ray1, viewer.scene)
      console.log(3)
      return cartesian
    }
  }
}
